/*
 * PException.h
 *
 *  Created on: Sep 6, 2013
 *      Author: yuliang
 */

#ifndef PEXCEPTION_H_
#define PEXCEPTION_H_

#include <exception>
#include <sstream>
#include <string.h>

using namespace std;

#ifndef USEERROREXCEPTION
#define USEERROREXCEPTION 1
#endif

// 定义字符出输出流
namespace {
	ostringstream g_ssEEPara;
}
// 获取定义
#define SET_PARA(msg) (::g_ssEEPara.str(""), (::g_ssEEPara << msg), ::g_ssEEPara.str())

// 系統层异常
#define STDERROR(err) CErrorException(err, "", __FUNCTION__, __LINE__, __FILE__)
// 应用层异常
#define USRERROR(info) CErrorException(-1, info, __FUNCTION__, __LINE__, __FILE__)


//
// 异常类，转换错误代码与错误描述
//
class CErrorException: public exception {
public:
    // 构造函数
    CErrorException(int iErr, string errInfo, const char* thrower, int line, const char* file) throw()
		: m_iErrNo(iErr), m_iLine(line), m_strFile(file),
		m_strThrower(thrower), m_strUserErrInfo(errInfo), m_pssExpInfo(new ostringstream) {
    	InitInfo();
    }
    // 析构函数
    virtual ~CErrorException(void) throw() { delete m_pssExpInfo; }
    // 继承于标准异常类的接口，返回异常信息
    virtual const char* what() const throw() { return m_strInfo.c_str(); }

    // 取得错误代码
    int GetErrNo(void) const throw() { return m_iErrNo; }
    // 设置错误代码
    void SetErrNo(int eErr) throw() { m_iErrNo = eErr; InitInfo(); }
    // 设置用户定义错误信息
    void SetUserErrInfo(const char* errInfo) throw() { m_strUserErrInfo = errInfo; InitInfo(); }
    // 设置异常抛出者
    void SetThrower(const char* thrower) throw()  { m_strThrower = thrower; InitInfo(); }
    // 获取异常抛出者
    const char* GetThrower(void) throw()  { return m_strThrower.c_str(); }
    // 获取错误信息
    const char* GetErrInfo(void) const throw() {
        if ((this->m_iErrNo > 131) || (this->m_iErrNo < 0))
            return m_strUserErrInfo.c_str();
        return strerror(this->m_iErrNo);
    }

private:
    void InitInfo() {
    	m_pssExpInfo->str("");
		*m_pssExpInfo << m_strFile << ":" << m_iLine << ":" << m_strThrower << ": error num "
				<< m_iErrNo	<< ", " << GetErrInfo();
    	m_strInfo = m_pssExpInfo->str();
    }

private:
    int     m_iErrNo;           // 错误代码
	int 	m_iLine;			// 行数
	string	m_strFile;			// 文件名
    string  m_strThrower;       // 抛出错误代码者
    string  m_strUserErrInfo;   // 用户定义错误代码
    ostringstream* m_pssExpInfo;
    string  m_strInfo;			// 保存异常信息
};

#endif /* PEXCEPTION_H_ */
